<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding:0;
            list-style:none;
        }
        .lunbo{
            margin: 100px auto;
            width:800px;
            height:500px;
            background-color:#ccc;
            overflow: hidden;
            user-select: none;
        }
        .btns{
            position:absolute;
            width: 800px;
            height:500px;
            z-index:1;
        }
        .btns div {
            position: absolute;
            width: 50px;
            height: 50px;
            top:0;
            bottom:0;
            margin: auto;
            font-size: 50px;
            font-weight: bold;
            color: white;
            text-align: center;
            cursor: pointer;
        }
        .btns .left{
            left:0;
            text-align: left;
        }
        .btns .right{
            right:0;
            text-align: right;
        }
        .lunbo .list{

            transition-duration: 0.8s;
        }
        .lunbo li,
        .lunbo li img{
            float:left;
            width:800px;
            height:500px;
        }
    </style>
</head>
<body>
<div class = "lunbo">
    <div class = "btns">
        <div class = "left"> < </div>
        <div class = "right"> > </div>
    </div>
    <ul class = "list"></ul>

</div>
<script>
    /*
    * 轮播图
    * 1.写布局
    * 2.调整位置：调整ul的位置，因为ul列表包裹着这些图片，ul列表移动，轮播图也就跟着动了(relative left/translateX)
    *
    * */
    //根据数据渲染内容 先向后台请求数据，根据数据生成页面，并且这个页面还能满足以下逻辑
    //能用const声明常量就用const 因为不希望别人能随便改代码
    const imgList = [ //用一个数组模拟后台返回来的数据
        "./imgs/01.jpg",
        "./imgs/02.jpg",
        "./imgs/03.jpg",
        "./imgs/04.jpg",
        "./imgs/05.jpg",
    ]

    //为什么要抽象出下面这个lunbo对象？因为这样抽象出来，lunbo对象中的所有函数方法操作的主体对象都是这个lunbo对象，里面所有的this指向也都是指向lunbo对象
    const lunbo = { //抽象出一个对象 描述整个轮播的状态
        length:imgList.length,
        el:document.querySelector(".list"), //需要被操作的元素
        current:0, //表示当前显示的是第几张 当前第0张
        changeState:function(num){ //需要抽象出来的切换状态函数 传入一个参数 表示向右切换第几张
            this.current += num //通过this访问到lunbo对象里的current属性 更新维护current的状态

            //还得对状态边界进行限制 防止边界溢出
            if(this.current < 0){ //维护右边边界
                this.current = this.length - 1
            }
            if(this.current >= this.length){ //维护左边边界
                this.current = 0
            }

        },
        render:function(){ //抽象出一个render函数渲染状态
            this.el.style.transform = `translateX(${-800 * this.current}px)`
        },
        init:function(){ //在轮播对象中抽象出一个方法 根据imgList中的数据初始化页面
            let str = ""
            imgList.forEach(img => {
                str += `<li><img src = "${img}"></li>` //将数组中每个被遍历到的元素添加进li标签
            })
            this.el.style.width = `${800 * this.length}px` //ul列表的宽度随着数组的长度的变化而变化
            this.el.innerHTML = str //最后将添加好的内容渲染出来
        },
        register:function(){ //在轮播对象中抽象出一个 注册点击事件的函数方法 通过this访问lunbo对象的内部自身属性
            this.leftBtn = document.querySelector(".left") //通过this将获取到的left绑定到lunbo对象的this.leftBtn属性中，
            // 这样只要在lunbo对象中就能访问并获取到这个属性
            this.rightBtn = document.querySelector(".right") //通过this将获取到的right绑定到lunbo对象的this.rightBtn属性中，
            // 这样只要在lunbo对象中就能访问并获取到这个属性

            this.rightBtn.onclick = () => { //箭头函数this强行绑定上下文 上一行和下一行的this是谁 外面的register函数被谁调用？
                //外面的register函数在121行被lunbo调用，所以这里面的this都指向lunbo 这样就有了current length el 等属性
                //this.current++ //修改状态 需要判断边界

                this.changeState(1) //向右移动一张图片
                this.render() //用抽象出来的状态渲染函数代替下面的渲染状态代码
                //this.el.style.transform = `translateX(${-800 * this.current}px)` //渲染状态
                //如果不用箭头函数绑定上下文 点击事件中的this指向点击事件函数onclick前面的调用者rightBtn 但是这个btn没有el属性
            }
            this.leftBtn.onclick = () => { //箭头函数this强行绑定上下文 上一行和下一行的this是谁 外面的register函数被谁调用？
                //外面的register函数在120行被lunbo调用，所以这里面的this都指向lunbo 这样就有了current length el 等属性
                //this.current-- //修改状态

                this.changeState(-1) //向左移动一张图片
                this.render() //用抽象出来的状态渲染函数代替下面的渲染状态代码
                //this.el.style.transform = `translateX(${-800 * this.current}px)` //渲染状态
                //如果不用箭头函数绑定上下文 点击事件中的this指向点击事件函数onclick前面的调用者leftBtn 但是这个btn没有el属性
            }
        },
        unregister:function (){ //抽象出一个解绑按钮的函数方法 通过下面的代码将点击按钮无效化
            this.leftBtn.onclick = this.rightBtn.onclick = null //清空按钮的点击事件属性
        },
        delay:3000, //对象中的延时属性，表示3000ms 毫秒
        autoPlay:function (){ //抽象出一个开启自动播放的函数方法
            //下面设置一个有规律的间隔时间定时器 将这个间隔时间定时器返回的编号用this.timer接收 使得在对象lunbo内部可以被访问到
            this.timer = setInterval(() => { //用箭头函数是为了解决this指向不明的问题 将this指向强行绑定到上下文中 即autoPlay函数在最下面被lunbo对象调用
                // this就指向lunbo对象 这样this就有 changeState render两个属性
                this.changeState(1)
                this.render()
            },this.delay)
            //this.timer = setInterval((function (){
            //    this.changeState(1)
            //    this.render()
            //}).bind(this),this.delay) //也可以用bind方法 将setInterval里面的回调函数的this指向 绑定到上下文当中的this指向
            //只需要将回调函数括起来bind就行
        },
        stopAutoPlay:function (){ //抽象出一个关闭自动播放的函数方法
            clearInterval(this.timer) //清除间隔时间定时器
        }
    }
    lunbo.init()
    lunbo.register()
    lunbo.autoPlay()


    /*function init({ul}){ //根据imgList中的数据初始化页面 通过结构赋值拿到lunbo中传入的形参ul
        let str = ""
        imgList.forEach(item => {
            str += `<li><img src = "${item}"></li>` //将数组中每个被遍历到的元素添加进li标签
        })
        ul.style.width = `${800 * length}px` //ul列表的宽度随着数组的长度的变化而变化
        ul.innerHTML = str //最后将添加好的内容渲染出来

    }*/
    //init(lunbo) //将对象lunbo传入
    //register(lunbo) //注册页面事件，将lunbo对象传入
    /*function register({current,el}){ //注册点击事件的函数 通过结构赋值拿到lunbo中传入的参数el元素
        let leftBtn = document.querySelector(".left")
        let rightBtn = document.querySelector(".right")

        rightBtn.onclick = function (){
            current++ //修改状态 需要判断边界
            if(current >= length){
                current = length - 1
            }
            el.style.transform = `translateX(${-800 * current}px)` //渲染状态
        }
        leftBtn.onclick = function (){
            current-- //修改状态
            if(current <= 0){
                current = 0
            }
            el.style.transform = `translateX(${-800 * current}px)` //渲染状态
        }
    }*/






</script>
</body>
</html>